# -*-conding=utf-8-*-
"""
调用cloud api 基类


错误类型:

ValueError: 传参错误
ServiceError: 远端服务错误

"""
from uuid import uuid4
import json

import traceback

import requests
from tools import redis_conn
from urllib.parse import urljoin, quote
from flask import current_app, request
from app.models import rangeModel
from tools.basic_tools import Tools
from flask_restx import abort
from app.api.v1.webhook.operate_config import skipped_push

# # 这里替换成使用flask 读取配置
# with open("./configs.yaml", "r+", encoding="utf-8") as file:
#     config = yaml.safe_load(file)



class ServiceError(Exception):
    """自定义服务错误类型"""

    def __init__(self, message) -> None:
        self.message = message

    def __str__(self) -> str:
        print("ServiceError: ",self.message)




class ZStackCloud(object):
    """云服务基础"""


    def __init__(self) -> None:
        """
            初始化参数
            job_uuid: 可指定job的uuid, 未指定， ZStack Cloud 会自动为api job生产一个uuid
            web_hook: 异步api, 指定一个回调url 用于接收api返回, 避免轮询去查询异步api的执行结果
        """
        # 校验是否存在登录信息
        if  not  current_app.config.get("ZSTACK_CLOUD"):
            raise ValueError("缺少必要参数")
        self.zstack = current_app.config["ZSTACK_CLOUD"]
        self.username = self.zstack["auth"]["username"]
        self.password = self.zstack["auth"]["password"]
        self.auth_url = self.zstack["auth"]["auth_url"]
        self.zone_uuid = self.zstack["zone_uuid"]
        # self.job_uuid = job_uuid
        # self.web_hook = web_hook
        self.headres = {"X-Web-Hook": self.zstack["webhook_url"]}

    def __enter__(self):
        """登录, 获取Session UUID"""
        # 缓存redis, 过期重新获取

        body = {
            "logInByAccount": {
                "accountName": self.username,
                "password": self.password
            }
        }
        session_id = redis_conn.get("zstack_Auth")
        if session_id:
            session_id = session_id.decode('utf-8')
        else:
            res = requests.request("put", urljoin(self.auth_url, "accounts/login"), data=json.dumps(body), headers=self.headres)
            result = self.__filter_response_body(res)
            session_id = result["uuid"]
            expiration = current_app.config["ZSTACK_CLOUD"]["expiration"]
            redis_conn.setex("zstack_Auth", expiration, session_id)
        # 获取uuid
        self.headres["Authorization"] = f"OAuth {session_id}"
        return self

    def __filter_response_body(self, response):
        """解析返回的响应数据"""
        if response.status_code == 200: # 成功
            result = json.loads(response.text)
            # print(result)
            if result.__contains__("inventories"):
                return result["inventories"]
            elif result.__contains__("inventory"):
                return result["inventory"]
            else:
                return result
        elif response.status_code == 202:
            return json.loads(response.text)
        elif response.status_code == 503:  # 错误, 收集错误信息
            try:
                result = json.loads(response.text)
                error = result["error"]
                if error.get("message"):
                    messages = error["messages"]
                    description = messages["message_cn"]
                else:
                    description = error["description"]
                print(result)
                abort(400, message=description)
            except json.decoder.JSONDecodeError as error:
                print(response.text)
                abort(500, message="传参错误")
        elif response.status_code == 500:
            print(response.text)
            abort(500, message="携带请求参数错误")
        else:
            print(response.text, "返回的数据", response.status_code)
            

    def __call__(self, method, url, params=None, data=None, **kwargs):
        """
            发送请求
            method: 请求类型
            url: url
            params:  Query 
            data: body
        """
        try:
            if kwargs.get("job_uuid"):
                self.headres["X-Job-UUID"] = kwargs.get("job_uuid")
            print(self.headres)
            url = urljoin(self.auth_url, url)
            if params:
                params_list = [f"q={k}={v}" for k, v in params.items() ]
                url = f"{url}?" + "&".join(params_list)

            self.headres["X-Web-Hook"] =  self.zstack["webhook_url"]

            res = requests.request(method, url, data=json.dumps(data), headers=self.headres)
            return self.__filter_response_body(res)
        except Exception :
            print(traceback.print_exc())
            abort(400, message="发送请求失败")

    def __exit__(self, exc_type, exc_val, exc_tb):
        """
            关闭资源, 异常处理
            exc_type: 异常类型
            exc_val: 异常的值
            exc_tb: 异常的内存地址
        """
        print(exc_type, exc_val, exc_tb)
        print("释放资源, 请求完后续记录数据库等操作")
        # 关闭资源
        return True
        
    


if __name__ == "__main__":
    with  ZStackCloud() as zc:
        # 查询镜像
        print(zc(method="get", url="images"))
